package com.managed.bean;

import com.marlboroug.articlesordered.ArticlesOrderedManagerRemote;
import com.marlboroug.entity.Articlesordered;
import com.marlboroug.entity.Users;
import com.marlboroug.users.UsersManagerRemote;
import com.util.CommandResult;
import com.util.OrderStatus;
import com.util.PasswordHash;
import java.io.IOException;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

/**
 * Bean Managé pour la page des comptes.
 *
 * @author Cyril Schumacher
 */
@ManagedBean(name = "account")
@SessionScoped
public class AccountBean implements Serializable {
    // <editor-fold defaultstate="collapsed" desc="Constantes.">
    /**
     * Adresse URL relative de la page de connexion.
     */
    private final static String _LOGIN_URL = "/faces/account/login.xhtml";
    /**
     * Adresse URL relative de la page affichant le profil de l'utilisateur.
     */
    private final static String _PROFIL_URL = "/faces/account/index.xhtml";
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Membres.">
    // <editor-fold defaultstate="collapsed" desc="Enterprise JavaBeans.">
    /**
     * Gestion des utilisateurs.
     */
    @EJB
    private UsersManagerRemote _usersManager;
    /**
     * Gestion des commandes.
     */
    @EJB
    private ArticlesOrderedManagerRemote _articlesOrderedManager;
    // </editor-fold>

    /**
     * Indication si l'utilisateur est connecté ou non.
     */
    private Boolean _isLogged;
    /**
     * Identifiant saisi par l'utilisateur.
     */
    private Users _user;
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Accesseurs/Mutateurs.">
    /**
     * Obtient la liste des commandes.
     *
     * @return Retourne la liste.
     */
    public List<Articlesordered> getOrders() {
        return _articlesOrderedManager.OrdersList(_user.getIDusers());
    }

    /**
     * Obtient les informations de l'utilisateur.
     *
     * @return Retourne un objet de type "Users".
     * @see com.marlboroug.entity.Users
     */
    public Users getUser() {
        return _user;
    }

    /**
     * Définit les informations de l'utilisateur.
     *
     * @param user Informations de l'utilisateur.
     */
    public void setUser(Users user) {
        _user = user;
    }

    /**
     * Obtient une valeur indiquant si l'utilisateur est connecté ou non.
     *
     * @return Retourne TRUE ou FALSE.
     */
    public Boolean getIsLogged() {
        return _isLogged;
    }

    /**
     * Obtient le status de la commande.
     *
     * @param statusId Identifiant de la status.
     * @return Retourne le status.
     */
    public String getOrderStatus(Integer statusId) {
        return OrderStatus.getById(statusId).toString();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Méthodes.">
    // <editor-fold defaultstate="collapsed" desc="Privées.">
    /**
     * Détermine si le nom d'utilisateur et le mot de passe sont valides.
     *
     * @return Retourne TRUE si le nom d'utilisateur et le mot de passe sont
     * valides, FALSE sinon.
     */
    private Boolean _checkUsernamePassword() throws NoSuchAlgorithmException {
        // Recherche le nom d'utilisateur.
        List<Users> usernameFound = _usersManager.AuthentificationUsername(_user.getUsername());
        if (usernameFound.size() == 1) {
            // Récupère l'identifiant selon le nom d'utilisateur.
            long usernameId = usernameFound.get(0).getIDusers();

            // Récupère le mot de passe de l'utilisateur et le hash.
            String password = PasswordHash.crypt(getUser().getPassword());
            _user.setPassword(password);
            
            // Vérifie le mot de passe de l'utilisateur.
            List<Users> passwordFound = _usersManager.AuthentificationPassword(_user.getPassword());
            if (passwordFound.size() == 1) {
                _user = _usersManager.find(usernameId);
                return true;
            }
        }

        // Si l'utilisateur n'a pas pu être créer, on signale l'erreur à 
        // l'utilisateur.
        FacesContext.getCurrentInstance().addMessage("id", new FacesMessage(FacesMessage.SEVERITY_ERROR,
                "Le nom d'utilisateur ou le mot de passe est incorrect.", null));
        return false;
    }

    // </editor-fold>
    /**
     * Redirige l'utilisateur si celui-ci est connecté.
     *
     * @throws IOException
     */
    public void isLogged() throws IOException {
        if (_isLogged == true) {

            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
            externalContext.redirect(externalContext.getRequestContextPath() + _PROFIL_URL);
        }
    }

    /**
     * Redirige l'utilisateur si celui-ci n'est pas connecté.
     *
     * @throws IOException
     */
    public void isNotLogged() throws IOException {
        if (_isLogged == false) {
            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
            externalContext.redirect(externalContext.getRequestContextPath() + _LOGIN_URL);
        }
    }

    /**
     * Connecte l'utilisateur.
     *
     * @return Retourne "success" si l'utilisateur est authentifié, "failure"
     * sinon.
     * @throws java.security.NoSuchAlgorithmException
     */
    public String login() throws NoSuchAlgorithmException {
        // Vérifie si le nom d'utilisateur et le mot de passe sont corrects.
        if (_checkUsernamePassword()) {
            _isLogged = true;
            return CommandResult.SUCCESS.toString();
        }

        return CommandResult.FAILURE.toString();
    }

    /**
     * Déconnecte l'utilisateur.
     *
     * @throws java.io.IOException
     */
    public void logout() throws IOException {
        // Indique que l'utilisateur n'est plus connecté et supprime 
        // les informations de ce son compte.
        _isLogged = false;
        setUser(new Users());

        // Redirige l'utilisateur vers la page de connexion.
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        externalContext.redirect(externalContext.getRequestContextPath() + _LOGIN_URL);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Initialisation de la classe.">
    /**
     * Initialise la classe après l'injection de dépendance.
     *
     * @see javax.annotation.PostConstruct
     */
    @PostConstruct
    public void initialize() {
        if (_isLogged == null) {
            _isLogged = false;
        }
        if (_user == null) {
            _user = new Users();
        }
    }
    // </editor-fold>
}
